﻿using System.Collections.Generic;
using System.Reflection;

namespace BLL.Utility
{
    /// <summary>
    /// 合并两个对象，会使用后一个对象的属性覆盖前一个对象的属性，同时第一个对象已经被破坏
    /// 比较规则是属性名称相同就覆盖
    /// 采用反射实现，请不要在循环内调用，会造成性能损失
    /// </summary>
    public class CopyProperties
    {
        public enum CopyOption
        {
            /// <summary>
            /// 后一个对象的属性值为Null时，该属性会被忽略
            /// </summary>
            IgnoreNull,
            /// <summary>
            /// 后一个对象的属性值为Null时，一样会覆盖前一个对象的属性
            /// </summary>
            ContainNull
        }

        /// <summary>
        /// 用第二个对象的属性覆盖第一个属性
        /// </summary>
        /// <typeparam name="T">类型</typeparam>
        /// <param name="target">需要被覆盖的对象</param>
        /// <param name="source">需要当作源的对象</param>
        /// <param name="ignoreList">忽略比较的属性列表</param>
        /// <param name="option">覆盖方法</param>
        public static void Compare<T>(T target, T source, IList<string> ignoreList = null, CopyOption option = CopyOption.IgnoreNull) where T : class
        {
            if (target == null || source == null)
            {
                return;
            }

            ignoreList = ignoreList ?? new List<string>();

            var properties = typeof(T).GetProperties(BindingFlags.Instance | BindingFlags.Public);
            foreach (var propertyInfo in properties)
            {
                var sourceValue = propertyInfo.GetValue(source, null);
                if (sourceValue == null && option == CopyOption.IgnoreNull)
                {
                    continue;
                }
                if (!ignoreList.Contains(propertyInfo.Name))
                {
                    propertyInfo.SetValue(target, sourceValue, null);
                }
            }
        }


    }
}